package com.qen.fx.custom.impl.pwd;

import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import com.qen.App;
import com.qen.fx.ViewIndex;
import com.qen.fx.custom.CustomBusiness;
import com.qen.fx.tools.ClipboardTool;
import com.qen.fx.tools.UUIDv1Generator;
import com.qen.plugin.notification.NotificationTool;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.event.ActionEvent;
import javafx.event.Event;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.control.*;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Paint;
import javafx.scene.text.Font;

import java.io.IOException;
import java.net.URL;
import java.util.ResourceBundle;
import java.util.UUID;
import java.util.regex.Pattern;

public class UuidGenerator extends CustomBusiness {

    @FXML
    private HBox nameHbox;
    @FXML
    private Label inputVbox;
    @FXML
    private Label dns;
    @FXML
    private TextField inSpace;
    @FXML
    private Button refresh;
    @FXML
    private Label x500;
    @FXML
    private Label oid;
    @FXML
    private Label url;
    @FXML
    private TextField inName;
    @FXML
    private Label nil;
    @FXML
    private Slider number;
    @FXML
    private HBox spaceHbox;
    @FXML
    private Label v1;
    @FXML
    private Button copy;
    @FXML
    private Label v3;
    @FXML
    private Label v4;
    @FXML
    private Label v5;
    @FXML
    private Label numberLabel;

    private int selectSpace = 1;
    private static final Pattern UUID_PATTERN_V3 = Pattern.compile(
            "^[0-9a-f]{8}-" +     // 32个十六进制字符，分成5段
                    "[0-9a-f]{4}-" +
                    "[0-9a-f]{4}-" +
                    "[0-9a-f]{4}-" +
                    "[0-9a-f]{12}$",      // 大小写不敏感
            Pattern.CASE_INSENSITIVE
    );
    private static final Pattern UUID_PATTERN_V5 = Pattern.compile(
            "^[0-9a-f]{8}-" +     // 32个十六进制字符，分成5段
                    "[0-9a-f]{4}-5" +                 // 版本号5
                    "[0-9a-f]{3}-" +
                    "([89abAB])" +        // 变种标识符
                    "[0-9a-f]{3}-" +
                    "[0-9a-f]{12}$",      // 大小写不敏感
            Pattern.CASE_INSENSITIVE
    );
    private String version = "V3";
//    private String space = "url";

    private String[] v3Space = new String[]{
            "6ba7b810-9dad-11d1-80b4-00c04fd430c8",
            "6ba7b811-9dad-11d1-80b4-00c04fd430c8",
            "6ba7b812-9dad-11d1-80b4-00c04fd430c8",
            "6ba7b814-9dad-11d1-80b4-00c04fd430c8"
    };

    @Override
    public VBox init() {
        return null;
    }

    @Override
    public void initialize(URL url, ResourceBundle resourceBundle) {

    }

    @FXML
    public void clickVersion(Event event) {
        Object obj = event.getSource();
        setActive((Label) obj);
        Label[] labels = new Label[]{nil, v1, v3, v4, v5};
        for (Label label : labels) {
            if (obj == label) {
                continue;
            }
            clearActive(label);
        }
        if (obj == v3 || obj == v5) {
            spaceHbox.setManaged(true);
            spaceHbox.setVisible(true);
            nameHbox.setManaged(true);
            nameHbox.setVisible(true);
        } else {
            spaceHbox.setManaged(false);
            spaceHbox.setVisible(false);
            nameHbox.setManaged(false);
            nameHbox.setVisible(false);
        }
        inSpace.setText(v3Space[selectSpace]);
        version = ((Label) obj).getText().trim();
        createUUIDs();
    }

    private void setActive(Label label) {
        label.setStyle("-fx-background-color: #CBE4CF;");
        label.setTextFill(Paint.valueOf("#178324"));
        Font font = new Font("System Bold", 20);
        label.setFont(font);
    }

    private void clearActive(Label label) {
        label.setStyle("-fx-background-color: #AAA;");
        label.setTextFill(Paint.valueOf("#000"));
        Font font = new Font(20);
        label.setFont(font);
    }

    @FXML
    public void inputSpace(ActionEvent actionEvent) {
        createUUIDs();
    }

    @FXML
    public void clickSpace(Event event) {
        Object obj = event.getSource();
        setActive((Label) obj);
        Label[] labels = new Label[]{dns, url, oid, x500};
        for (int i = 0; i < labels.length; i++) {
            Label label = labels[i];
            if (obj == label) {
                inSpace.setText(v3Space[i]);
                selectSpace = i;
                continue;
            }
            clearActive(label);
        }
//        space = ((Label) obj).getText().trim();
        createUUIDs();
    }

    @FXML
    public void refresh(Event event) {
        createUUIDs();
    }

    @FXML
    public void copy(Event event) {
        String token = inputVbox.getText();
        if (StrUtil.isBlank(token)) {
            return;
        }
        ClipboardTool.copyToClipboard(token);
        NotificationTool.message("复制成功!");
    }

    @FXML
    public void inputName(ActionEvent actionEvent) {
        createUUIDs();
    }

    public UuidGenerator() {
        FXMLLoader fxmlLoader = new FXMLLoader(App.class.getResource(ViewIndex.UuidGeneratorFXML));
        fxmlLoader.setRoot(this);
        fxmlLoader.setController(this);
        try {
            fxmlLoader.load();
        } catch (IOException e) {
            e.printStackTrace();
        }
        number.valueProperty().addListener((observableValue, number, t1) -> {
            int quantity = t1.intValue();

            numberLabel.setText("数量(" + quantity + ")");
            createUUIDs();
        });
        inName.textProperty().addListener((observableValue, s, t1) -> {
//            if ("v3".equals(version)) {
//                if (!isValidUUIDv3Format(t1)) {
//                    NotificationTool.error("命名空间格式不正确!");
//                    return;
//                }
//            } else if ("v5".equals(version)) {
//                if (!isValidUUIDv5Format(t1)) {
//                    NotificationTool.error("命名空间格式不正确!");
//                    return;
//                }
//            }
            createUUIDs();
        });
        inSpace.setText(v3Space[selectSpace]);
        createUUIDs();
    }

    private void createUUIDs() {
        int num = (int) number.getValue();
        StringBuilder str = new StringBuilder();
        for (int i = 0; i < num; i++) {
            if (i > 0) {
                str.append("\n");
            }
            str.append(createUUID());
        }
        inputVbox.setText(str.toString());
    }

    private String createUUID() {
        if ("NIL".equals(version)) {
            Integer[] ar = NumberUtil.generateBySet(0, Integer.MAX_VALUE, 2);
            UUID uuid = new UUID(ar[0], ar[1]);
            System.out.println(uuid.version());
            return uuid.toString();
        } else if ("V1".equals(version)) {
            UUID uuid = UUIDv1Generator.generateVersion1UUID(UUIDv1Generator.getNodeIdentifier());
            System.out.println(uuid.version());
            return uuid.toString();
        } else if ("V3".equals(version)) {
            String name = inName.getText();
            String namespace = inSpace.getText();
            UUID uuid = UUID.nameUUIDFromBytes((namespace + ":" + name).getBytes());
            System.out.println(uuid.version());
            return uuid.toString();
        } else if ("V4".equals(version)) {
            UUID uuid = UUID.randomUUID();
            System.out.println(uuid.version());
            return uuid.toString();
//        } else if ("V5".equals(version)) {
//            String name = inName.getText();
//            String namespace = inSpace.getText();
//            UUID uuid = UUID.nameUUIDFromBytes(("" + namespace + name).getBytes());
//            System.out.println(uuid.version());
//            return uuid.toString();
        }
        return "";
    }

    private boolean isValidUUIDv3Format(String uuidStr) {
        return UUID_PATTERN_V3.matcher(uuidStr).matches();
    }

    private boolean isValidUUIDv5Format(String uuidStr) {
        return UUID_PATTERN_V5.matcher(uuidStr).matches();
    }

}
